package com.cmc.cloud.cmclink.doc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmc.cloud.cmclink.doc.api.document.emums.BaseCodeCategoryEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.SoDataSourceEnum;
import com.cmc.cloud.cmclink.doc.api.document.rep.VgmRespDto;
import com.cmc.cloud.cmclink.doc.api.document.req.so.SoForecastBaseVO;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.VgmErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.convert.VgmConvert;
import com.cmc.cloud.cmclink.doc.dto.VgmTelAndEmailInfoDto;
import com.cmc.cloud.cmclink.doc.entity.BaseCodeDO;
import com.cmc.cloud.cmclink.doc.entity.VgmDO;
import com.cmc.cloud.cmclink.doc.entity.VoyageLockDO;
import com.cmc.cloud.cmclink.doc.mapper.*;
import com.cmc.cloud.cmclink.doc.service.VgmService;
import com.cmc.cloud.cmclink.doc.util.CheckUtil;
import com.cmc.cloud.cmclink.doc.util.I18nsUtil;
import com.cmc.cloud.cmclink.doc.util.LocalDateTimeUtil;
import com.cmc.cloud.cmclink.doc.vo.vgm.*;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cmes.framework.security.core.util.SecurityFrameworkUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * VMG信息 Service 实现类
 *
 * @author 集运管理员
 */
@Service
@Validated
public class VgmServiceImpl implements VgmService {

    private final String SUCCESSEN = "SUCCESS";
    private final String SUCCESSCN = "成功";

    @Resource
    private VgmMapper vgmMapper;

    @Resource
    private VoyageLockMapper voyageLockMapper;

    @Resource
    private LocalDateTimeUtil localDateTimeUtil;

    @Resource
    private BaseCodeMapper baseCodeMapper;

    @Resource
    private I18nsUtil i18nsUtil;

    @Resource
    private BlnoMapper blnoMapper;

    @Resource
    private SoMapper soMapper;

    @Resource
    private SoForecastMapper soForecastMapper;

    /**
     * 插入时判断是否存在相同的船名航次+箱号如果存在不允许导入已经锁船不允许添加
     *
     * @param vgmImportReqVoList
     * @param vesselCode
     * @param voyage
     * @param port
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<VgmImportReqVO> importVgm(List<VgmImportReqVO> vgmImportReqVoList, String vesselCode, String voyage, String port) {
        if (CollectionUtils.isEmpty(vgmImportReqVoList)) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_NOT_ALLOW_NULL);
        }
        VgmImportReqVO vgmImportReqVo = vgmImportReqVoList.get(0);
        if (StringUtils.isNotEmpty(vgmImportReqVo.getBlNo()) && StringUtils.isNotEmpty(vgmImportReqVo.getBookingNo())) {
            checkVgmCntrNum(vgmImportReqVo.getBookingNo(), vgmImportReqVo.getBlNo(), vgmImportReqVoList.size());
        }
        List<VgmImportReqVO> checkResult = this.check(vgmImportReqVoList, vesselCode, voyage, port);
        Optional<VgmImportReqVO> optionalVgmImportReqVo = checkResult.stream().filter(item -> item.getBlockFlag()).findAny();
        if (optionalVgmImportReqVo.isPresent()) {
            return checkResult;
        }
        Locale currentLocale = LocaleContextHolder.getLocale();
        //只过滤check成功的
        List<VgmImportReqVO> filterVgmList = checkResult.stream().filter(entity -> !entity.getBlockFlag()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(filterVgmList)) {
            return checkResult;
        }
        List<VgmDO> vgmDoList = new ArrayList<>(168);
        filterVgmList.forEach(item -> {
            VgmDO vgmDo = VgmConvert.INSTANCE.convert(item);
            if (StringUtils.isBlank(item.getDataSource())) {
                vgmDo.setDataSource(SoDataSourceEnum.MANUAL.getValue());
            }
            if (StringUtils.isNotBlank(item.getTime())) {
                vgmDo.setTime(localDateTimeUtil.timeConvert(item.getTime()));
            }
            vgmDo.setVesselCode(vesselCode);
            vgmDo.setVoyage(voyage);
            vgmDo.setCurrentPort(port);
            vgmDoList.add(vgmDo);
        });
        vgmMapper.insertBatch(vgmDoList);
        return checkResult;
    }

    /**
     * 1、校验船期是否锁定
     * 2、校验导入的数据中是否有重复的箱号
     * 3、校验是否已经导入过
     *
     * @param vgmImportReqVoList
     * @param vesselCode
     * @param voyage
     * @param port
     * @return
     */
    @Override
    public List<VgmImportReqVO> check(List<VgmImportReqVO> vgmImportReqVoList, String vesselCode, String voyage, String port) {
        Locale currentLocale = LocaleContextHolder.getLocale();
        checkVoyageLock(vesselCode, voyage, port);
        //初始话所有数据为成功的
        vgmImportReqVoList.forEach(item -> {
            if (StringUtils.isBlank(item.getDataSource())) {
                item.setDataSource(SoDataSourceEnum.MANUAL.getValue());
            }
            item.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.SUCCESS.getCode(), currentLocale));
            item.setBlockFlag(false);
        });
        //处理表格内的重复
        Map<String, Long> listMap = vgmImportReqVoList.stream().collect(Collectors.groupingBy(VgmImportReqVO::getCntrNo, Collectors.counting()));
        Map<String, Long> upOne = listMap.entrySet().stream().filter(entry ->
                entry.getValue() > 1
        ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        List<String> importCntrNos = vgmImportReqVoList.stream().map(VgmImportReqVO::getCntrNo).collect(Collectors.toList());
        //修改时会传ID需要过滤掉自己，修改时只会有一条数据
        Long id = vgmImportReqVoList.get(0).getId();
        List<String> cntrNos = vgmMapper.selectCntrNo(vesselCode, voyage, id);

        //取称重方式
        LambdaQueryWrapperX<BaseCodeDO> lambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        lambdaQueryWrapperX.eq(BaseCodeDO::getCodeCategory, BaseCodeCategoryEnum.VGM_TYPE.getValue())
                .eq(BaseCodeDO::getEnable, true);
        List<BaseCodeDO> baseCodeDoList = baseCodeMapper.selectList(lambdaQueryWrapperX);
        if (CollectionUtils.isEmpty(baseCodeDoList)) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_TYPE_CODE_NOT_EXIST);
        }
        List<String> typeCodes = baseCodeDoList.stream().map(BaseCodeDO::getCode).collect(Collectors.toList());
        List<String> containCntrNos = new ArrayList<>(importCntrNos);
        if (CollectionUtils.isNotEmpty(cntrNos)) {
            containCntrNos.retainAll(cntrNos);
        }
        //提示验证
        for (VgmImportReqVO vgmImportReqVo : vgmImportReqVoList) {
            //重量控制
            if (vgmImportReqVo.getWeight().compareTo(new BigDecimal(2200)) < 0) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.VGM_WEIGHT_MIN.getCode(), currentLocale));
                continue;
            }

            if (vgmImportReqVo.getWeight().compareTo(new BigDecimal(35000)) > 0) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.VGM_WEIGHT_MAX.getCode(), currentLocale));
                continue;
            }
            //箱号校验
            if (!CheckUtil.isValidCntrNo(vgmImportReqVo.getCntrNo())) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.CNTR_IS_NOT_VALID.getCode(), currentLocale));
                continue;
            }
        }
        //阻塞验证
        for (VgmImportReqVO vgmImportReqVo : vgmImportReqVoList) {
            //时间格式
            if (StringUtils.isNotBlank(vgmImportReqVo.getTime()) && localDateTimeUtil.isValid(vgmImportReqVo.getTime())) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.TIME_IS_NOT_VALID.getCode(), currentLocale));
                vgmImportReqVo.setBlockFlag(true);
                continue;
            }
            //签单地址
            if (StringUtils.isNotBlank(vgmImportReqVo.getAddress()) && CheckUtil.containsNoEnglish(vgmImportReqVo.getAddress())) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.ADDRESS_CONTENT_EN.getCode(), currentLocale));
                vgmImportReqVo.setBlockFlag(true);
                continue;
            }
            //签单方式
            if (StringUtils.isNotBlank(vgmImportReqVo.getSignature()) && CheckUtil.containsNoEnglish(vgmImportReqVo.getSignature())) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.SIGN_CONTENT_EN.getCode(), currentLocale));
                vgmImportReqVo.setBlockFlag(true);
                continue;
            }
            //称重方式
            if (!typeCodes.contains(vgmImportReqVo.getTypeCode())) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.TYPE_CODE_NOT_EXISTS.getCode(), currentLocale));
                vgmImportReqVo.setBlockFlag(true);
                continue;
            }
            //箱号已存在
            if (CollectionUtils.isNotEmpty(containCntrNos) && CollectionUtils.isNotEmpty(cntrNos)) {
                if (containCntrNos.contains(vgmImportReqVo.getCntrNo())) {
                    vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.CNTR_NO_EXIST.getCode(), currentLocale));
                    vgmImportReqVo.setBlockFlag(true);
                    continue;
                }
            }
            //箱号重复
            if (!upOne.isEmpty() && null != upOne.get(vgmImportReqVo.getCntrNo())) {
                vgmImportReqVo.setMsg(i18nsUtil.getMessage(VgmErrorCodeConstants.CNTR_NO_REPEAT.getCode(), currentLocale));
                vgmImportReqVo.setBlockFlag(true);
                continue;
            }
        }

        return vgmImportReqVoList;
    }

    public void checkVoyageLock(String vesselCode, String voyage, String port) {
        LambdaQueryWrapperX<VoyageLockDO> voyageLockDoLambda = new LambdaQueryWrapperX<>();
        voyageLockDoLambda.eq(VoyageLockDO::getVesselCode, vesselCode)
                .eq(VoyageLockDO::getVoyage, voyage)
                .eq(VoyageLockDO::getPortCode, port)
                .eq(VoyageLockDO::getVoyageLockFlag, true);
        Long count = voyageLockMapper.selectCount(voyageLockDoLambda);
        if (count > 0L) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_VESSEL_IS_LOCK);
        }
    }

    /**
     * 校验是否存在，是否自己的数据，是否锁船，船名航次加箱号是否存在在
     *
     * @param updateReqVO 更新信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateVgm(VgmUpdateReqVO updateReqVO) {
        validateVgmExists(updateReqVO.getId());
        if (!Objects.equals(updateReqVO.getOperationSource(), SoDataSourceEnum.WEB.getValue())) {
            checkVaild(updateReqVO.getId());
        }
        checkVoyageLock(updateReqVO.getVesselCode(), updateReqVO.getVoyage(), updateReqVO.getCurrentPort());

        VgmCreateReqVO vgmCreateReqVo = VgmConvert.INSTANCE.convertVgmCreateVo(updateReqVO);
        checkVgm(vgmCreateReqVo);
        LambdaQueryWrapperX<VgmDO> vgmDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        vgmDoLambdaQueryWrapperX.eq(VgmDO::getVesselCode, updateReqVO.getVesselCode())
                .eq(VgmDO::getVoyage, updateReqVO.getVoyage())
                .eq(VgmDO::getCntrNo, updateReqVO.getCntrNo())
                .ne(VgmDO::getId, updateReqVO.getId());
        Long count = vgmMapper.selectCount(vgmDoLambdaQueryWrapperX);
        if (count > 0L) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_EXISTS);
        }
        VgmDO updateObj = VgmConvert.INSTANCE.convert(updateReqVO);
        if (StringUtils.isNotBlank(updateReqVO.getTime())) {
            updateObj.setTime(localDateTimeUtil.timeConvert(updateReqVO.getTime()));
        }
        vgmMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteVgm(Long id) {
        deleteCheck(id);
        checkVaild(id);
        vgmMapper.deleteById(id);
    }

    public void deleteCheck(Long id) {
        VgmDO vgmDo = vgmMapper.selectById(id);
        if (null == vgmDo) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_NOT_EXISTS);
        }
        if (SoDataSourceEnum.WEB.getValue().equals(vgmDo.getDataSource())) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.WEB_NOT_DELETE);
        }
    }

    private void validateVgmExists(Long id) {
        if (vgmMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_NOT_EXISTS);
        }
    }

    /**
     * 只允许操作自己创建的数据
     *
     * @param id
     */
    private void checkVaild(Long id) {
        LambdaQueryWrapperX<VgmDO> vgmDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        vgmDoLambdaQueryWrapperX.eq(VgmDO::getId, id)
                .ne(VgmDO::getCreator, SecurityFrameworkUtils.getLoginUserId());
        Long count = vgmMapper.selectCount(vgmDoLambdaQueryWrapperX);
        if (count > 0L) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_OPRATOR_NOT_ALLOW);
        }
    }

    @Override
    public PageResult<VgmDO> getVgmPage(VgmPageReqVO reqVo) {
        IPage<VgmDO> page = Page.of(reqVo.getPageNo(), reqVo.getPageSize());

        IPage<VgmDO> result = vgmMapper.selectPageList(page, reqVo);
        return new PageResult<VgmDO>(result.getRecords(), result.getTotal());
    }

    public void checkVgm(VgmCreateReqVO vgmCreateReqVo) {
        LambdaQueryWrapperX<BaseCodeDO> lambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        lambdaQueryWrapperX.eq(BaseCodeDO::getCodeCategory, BaseCodeCategoryEnum.VGM_TYPE.getValue())
                .eq(BaseCodeDO::getEnable, true);
        List<BaseCodeDO> baseCodeDoList = baseCodeMapper.selectList(lambdaQueryWrapperX);
        if (CollectionUtils.isEmpty(baseCodeDoList)) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_TYPE_CODE_NOT_EXIST);
        }
        List<String> typeCodes = baseCodeDoList.stream().map(BaseCodeDO::getCode).collect(Collectors.toList());
        if (StringUtils.isNotBlank(vgmCreateReqVo.getAddress()) && CheckUtil.containsNoEnglish(vgmCreateReqVo.getAddress())) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_ADDRESS);
        }
        if (StringUtils.isNotBlank(vgmCreateReqVo.getSignature()) && CheckUtil.containsNoEnglish(vgmCreateReqVo.getSignature())) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_SIGN);
        }

        if (StringUtils.isNotBlank(vgmCreateReqVo.getTime()) && localDateTimeUtil.isValid(vgmCreateReqVo.getTime())) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_TIME);
        }

        if (!typeCodes.contains(vgmCreateReqVo.getTypeCode())) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_TYPE_CODE_NOT_EXIST);
        }
        //查询订舱预配箱是否小于vgm维护箱
        if (StringUtils.isNotEmpty(vgmCreateReqVo.getBookingNo()) && StringUtils.isNotEmpty(vgmCreateReqVo.getBlNo())) {
            checkVgmCntrNum(vgmCreateReqVo.getBookingNo(), vgmCreateReqVo.getBlNo(), 0);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createVgm(VgmCreateReqVO vgmCreateReqVo) {
        this.checkVoyageLock(vgmCreateReqVo.getVesselCode(), vgmCreateReqVo.getVoyage(), vgmCreateReqVo.getCurrentPort());
        this.checkVgm(vgmCreateReqVo);
        LambdaQueryWrapperX<VgmDO> vgmDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        vgmDoLambdaQueryWrapperX.eq(VgmDO::getVesselCode, vgmCreateReqVo.getVesselCode())
                .eq(VgmDO::getVoyage, vgmCreateReqVo.getVoyage())
                .eq(VgmDO::getCntrNo, vgmCreateReqVo.getCntrNo());
        Long count = vgmMapper.selectCount(vgmDoLambdaQueryWrapperX);
        if (count > 0L) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_EXISTS);
        }
        VgmDO vgmDo = VgmConvert.INSTANCE.convert(vgmCreateReqVo);
        if (StringUtils.isBlank(vgmCreateReqVo.getDataSource())) {
            vgmDo.setDataSource(SoDataSourceEnum.MANUAL.getValue());
        }
        if (StringUtils.isNotBlank(vgmCreateReqVo.getTime())) {
            vgmDo.setTime(localDateTimeUtil.timeConvert(vgmCreateReqVo.getTime()));
        }
        vgmMapper.insert(vgmDo);
    }

    @Override
    public List<VgmDO> getVgm(VgmQueryVO reqVo) {
        LambdaQueryWrapperX<VgmDO> vgmDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        vgmDoLambdaQueryWrapperX.eq(VgmDO::getVesselCode, reqVo.getVesselCode())
                .eq(VgmDO::getVoyage, reqVo.getVoyage())
                .eqIfPresent(VgmDO::getCurrentPort, reqVo.getCurrentPort())
                .eqIfPresent(VgmDO::getCntrNo, reqVo.getCntrNo())
                .eqIfPresent(VgmDO::getBlNo, reqVo.getBlNo())
                .eqIfPresent(VgmDO::getDataSource, reqVo.getDataSource());
        if (CollectionUtils.isNotEmpty(reqVo.getCreators())) {
            vgmDoLambdaQueryWrapperX.inIfPresent(VgmDO::getCreator, reqVo.getCreators());
        }
        return vgmMapper.selectList(vgmDoLambdaQueryWrapperX);
    }

    @Override
    public List<VgmDO> getVgmInfo(VgmQueryInfoVO vgmQueryInfoVo) {
        LambdaQueryWrapperX<VgmDO> vgmDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        vgmDoLambdaQueryWrapperX.eq(VgmDO::getVesselCode, vgmQueryInfoVo.getVesselCode())
                .eq(VgmDO::getVoyage, vgmQueryInfoVo.getVoyage())
                .inIfPresent(VgmDO::getCntrNo, vgmQueryInfoVo.getCntrNo());
        return vgmMapper.selectList(vgmDoLambdaQueryWrapperX);
    }

    @Override
    public List<VgmDO> getVgmByBlnos(List<String> blnos) {
        LambdaQueryWrapperX<VgmDO> vgmDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        vgmDoLambdaQueryWrapperX.inIfPresent(VgmDO::getBlNo, blnos);
        return vgmMapper.selectList(vgmDoLambdaQueryWrapperX);
    }

    private static final DateTimeFormatter FOR_MATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrupdateVgmInfo(List<VgmCreateReqVO> vgmInfoList) {
        VgmCreateReqVO vgmInfo = vgmInfoList.get(0);
        vgmInfoList.forEach(this::checkVgm);
        //判断是否锁船
        this.checkVoyageLock(vgmInfo.getVesselCode(), vgmInfo.getVoyage(), vgmInfo.getCurrentPort());
        List<String> cntrNos = vgmInfoList.stream().map(VgmCreateReqVO::getCntrNo).collect(Collectors.toList());
        //过滤出EDI的数据
        List<VgmDO> vgmDos = vgmMapper.selectList(new LambdaQueryWrapperX<VgmDO>()
                .eq(VgmDO::getVesselCode, vgmInfo.getVesselCode())
                .eq(VgmDO::getVoyage, vgmInfo.getVoyage()).inIfPresent(VgmDO::getCntrNo, cntrNos)
                .neIfPresent(VgmDO::getDataSource, SoDataSourceEnum.WEB.getValue()));
        if (CollectionUtils.isNotEmpty(vgmDos)) {
            List<String> ediCntrNos = vgmDos.stream().map(VgmDO::getCntrNo).collect(Collectors.toList());
            //更新EDI的数据，只更新edi的Blno
            vgmDos.forEach(e -> {
                e.setBlNo(vgmInfo.getBlNo());
                VgmUpdateReqVO vgmUpdateReqVO = BeanUtil.copyProperties(e, VgmUpdateReqVO.class, "time");
                vgmUpdateReqVO.setTime(e.getTime().format(FOR_MATTER));
                updateVgm(vgmUpdateReqVO);
            });
            vgmInfoList.removeIf(e -> ediCntrNos.contains(e.getCntrNo()));
        }
        int delete = 0;
        if (CollectionUtils.isNotEmpty(vgmInfoList)) {
            delete = vgmMapper.delete(new LambdaQueryWrapperX<VgmDO>()
                    .eq(VgmDO::getVesselCode, vgmInfo.getVesselCode())
                    .eq(VgmDO::getVoyage, vgmInfo.getVoyage())
                    .inIfPresent(VgmDO::getCntrNo, vgmInfoList.stream().map(VgmCreateReqVO::getCntrNo).collect(Collectors.toList())));
            if (delete >= 0) {
                List<VgmDO> vgmList = vgmInfoList.stream().map(e -> {
                    VgmDO vgmDo = VgmConvert.INSTANCE.convert(e);
                    vgmDo.setTime(localDateTimeUtil.timeConvert(e.getTime()));
                    return vgmDo;
                }).collect(Collectors.toList());
                vgmMapper.insertBatch(vgmList);
            }
        }
    }

    @Override
    public VgmDO getVgmDetail(Long vgmId) {
        return vgmMapper.selectById(vgmId);
    }

    /**
     * 查询发货人电话和邮箱，如果SI查不到就查询SO
     *
     * @param vgmRespDtos
     */
    @Override
    public void queryTelAndEmailInfo(List<VgmRespDto> vgmRespDtos) {

        List<String> bkgVesselCodes = vgmRespDtos.stream().map(VgmRespDto::getVesselCode).collect(Collectors.toList());
        List<String> voyages = vgmRespDtos.stream().map(VgmRespDto::getVoyage).collect(Collectors.toList());
        List<String> cntrNos = vgmRespDtos.stream().map(VgmRespDto::getCntrNo).collect(Collectors.toList());
        List<VgmTelAndEmailInfoDto> vgmTelAndEmailBlnoInfoDtos = blnoMapper.selectTelAndEmailInfo(bkgVesselCodes, voyages, cntrNos);

        List<String> blnos = new ArrayList<>(64);

        Map<String, List<VgmTelAndEmailInfoDto>> listMapBlno = vgmTelAndEmailBlnoInfoDtos.stream().collect(Collectors.groupingBy(item -> item.getVesselCode() + item.getVoyage() + item.getCntrNo()));
        for (VgmRespDto vgmRespDto : vgmRespDtos) {
            String key = vgmRespDto.getVesselCode() + vgmRespDto.getVoyage() + vgmRespDto.getCntrNo();
            if (listMapBlno.containsKey(key)) {
                VgmTelAndEmailInfoDto vgmTelAndEmailInfoDto = listMapBlno.get(key).get(0);
                if (StringUtils.isBlank(vgmTelAndEmailInfoDto.getEmail()) || StringUtils.isBlank(vgmTelAndEmailInfoDto.getTelephone())) {
                    blnos.add(vgmTelAndEmailInfoDto.getBlno());
                }
                vgmRespDto.setEmail(vgmTelAndEmailInfoDto.getEmail());
                vgmRespDto.setTelephone(vgmTelAndEmailInfoDto.getTelephone());
                if (StringUtils.isBlank(vgmRespDto.getBlNo())) {
                    vgmRespDto.setBlNo(vgmTelAndEmailInfoDto.getBlno());
                }
            }
        }
        if (CollectionUtils.isNotEmpty(blnos)) {
            List<VgmTelAndEmailInfoDto> vgmTelAndEmailSoInfoDtos = soMapper.selectTelAndEmailSoInfo(blnos);
            Map<String, List<VgmTelAndEmailInfoDto>> listMapSo = vgmTelAndEmailSoInfoDtos.stream().collect(Collectors.groupingBy(VgmTelAndEmailInfoDto::getBlno));
            for (VgmRespDto vgmRespDto : vgmRespDtos) {
                if (listMapSo.containsKey(vgmRespDto.getBlNo())) {
                    VgmTelAndEmailInfoDto vgmTelAndEmailInfoDto = listMapSo.get(vgmRespDto.getBlNo()).get(0);
                    if (StringUtils.isNotBlank(vgmTelAndEmailInfoDto.getEmail()) && StringUtils.isNotBlank(vgmTelAndEmailInfoDto.getTelephone())) {
                        vgmRespDto.setEmail(vgmTelAndEmailInfoDto.getEmail());
                        vgmRespDto.setTelephone(vgmTelAndEmailInfoDto.getTelephone());
                    }
                }
            }
        }

    }

    @Override
    public void changeSiVgm(List<VgmCreateReqVO> vgmCreateReqVOList) {

    }

    @Override
    public List<VgmDO> getVgmEdi(VgmQueryEdiVO reqVo) {
        LambdaQueryWrapperX<VgmDO> vgmDoLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        vgmDoLambdaQueryWrapperX.eq(VgmDO::getVesselCode, reqVo.getVesselCode())
                .eq(VgmDO::getVoyage, reqVo.getVoyage())
                .eqIfPresent(VgmDO::getCurrentPort, reqVo.getCurrentPort())
                .eqIfPresent(VgmDO::getCntrNo, reqVo.getCntrNo())
                .inIfPresent(VgmDO::getBlNo, reqVo.getBlNos())
                .eqIfPresent(VgmDO::getDataSource, reqVo.getDataSource());
        if (CollectionUtils.isNotEmpty(reqVo.getCreators())) {
            vgmDoLambdaQueryWrapperX.inIfPresent(VgmDO::getCreator, reqVo.getCreators());
        }
        return vgmMapper.selectList(vgmDoLambdaQueryWrapperX);
    }

    /**
     * 校验订舱预配箱是否小于VGM维护的箱
     *
     * @param bookingNum
     * @param blno
     */
    private void checkVgmCntrNum(String bookingNum, String blno, long importSize) {
        List<SoForecastBaseVO> soForecastList = soForecastMapper.selectByBookingNo(bookingNum);
        long forecastCntrNum = 0L;
        if (CollectionUtils.isNotEmpty(soForecastList)) {
            forecastCntrNum = soForecastList.stream().mapToLong(SoForecastBaseVO::getCntrQuantity).sum();
        }
        if (forecastCntrNum <= 0L) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_CNTR_NUM_ERROR);
        }
        LambdaQueryWrapperX<VgmDO> wrapperX = new LambdaQueryWrapperX<>();
        wrapperX.eq(VgmDO::getBlNo, blno);
        Long vgmConut = vgmMapper.selectCount(wrapperX);
        if (vgmConut >= forecastCntrNum || importSize > forecastCntrNum) {
            throw ServiceExceptionUtil.exception(VgmErrorCodeConstants.VGM_CNTR_NUM_ERROR);
        }

    }
}
